from typing import Dict, List, Tuple

from .token import BosonToken
from .grammar_node import BosonGrammarNode
from .grammar import BosonGrammar


class BosonParser:
    def __init__(self):
        self.__terminal_index_mapping: Dict[str, int] = {
            '!symbol_12': 0,
            '!symbol_2': 1,
            '$': 2,
            '!symbol_13': 3,
            '!symbol_1': 4,
            'name': 5,
            '!symbol_14': 6,
            'string': 7,
            '!symbol_5': 8,
            '!symbol_10': 9,
            '!symbol_15': 10,
            '!symbol_19': 11,
            'regular': 12,
            '!symbol_20': 13,
            '!symbol_11': 14,
            '!symbol_16': 15,
            '!symbol_7': 16,
            '!symbol_6': 17,
            '!symbol_4': 18,
            '!symbol_17': 19,
            'number': 20,
            '!symbol_9': 21,
            '!symbol_3': 22,
            '!symbol_18': 23,
            '!symbol_8': 24
        }
        self.__sparse_action_table: Dict[int, Dict[int, str]] = {
            0: {4: 's8', 5: 's7'},
            1: {2: 'a'},
            2: {2: 'r53', 4: 's8', 5: 's7'},
            3: {2: 'r49', 4: 'r49', 5: 'r49'},
            4: {2: 'r32', 4: 'r32', 5: 'r32'},
            5: {2: 'r42', 4: 'r42', 5: 'r42'},
            6: {2: 'r59', 4: 'r59', 5: 'r59'},
            7: {21: 's43', 22: 's44'},
            8: {5: 's14', 7: 's12', 17: 's9'},
            9: {5: 's19'},
            10: {1: 's15', 5: 's14', 7: 's12', 17: 's9'},
            11: {1: 'r71', 5: 'r71', 7: 'r71', 17: 'r71'},
            12: {1: 'r44', 5: 'r44', 7: 'r44', 17: 'r44'},
            13: {1: 'r90', 5: 'r90', 7: 'r90', 17: 'r90'},
            14: {1: 'r92', 5: 'r92', 7: 'r92', 17: 'r92'},
            15: {2: 'r65', 4: 'r65', 5: 'r65'},
            16: {1: 'r27', 5: 'r27', 7: 'r27', 17: 'r27'},
            17: {16: 's42'},
            18: {16: 'r88', 24: 'r88'},
            19: {22: 's20'},
            20: {5: 's25', 6: 's27', 7: 's24', 17: 's9', 20: 's26'},
            21: {16: 'r39', 24: 'r39'},
            22: {10: 'r16', 16: 'r16', 24: 'r16'},
            23: {10: 'r18', 16: 'r18', 24: 'r18'},
            24: {10: 'r20', 16: 'r20', 24: 'r20'},
            25: {10: 'r21', 16: 'r21', 24: 'r21'},
            26: {10: 'r81', 16: 'r81', 24: 'r81'},
            27: {5: 's25', 6: 's27', 7: 's24', 17: 's9', 20: 's26'},
            28: {24: 's29'},
            29: {5: 's25', 6: 's27', 7: 's24', 17: 's9', 20: 's26'},
            30: {10: 'r12', 24: 's33'},
            31: {10: 'r58', 24: 'r58'},
            32: {10: 'r91', 24: 'r91'},
            33: {5: 's25', 6: 's27', 7: 's24', 10: 'r8', 17: 's9', 20: 's26'},
            34: {10: 's35'},
            35: {10: 'r69', 16: 'r69', 24: 'r69'},
            36: {10: 'r25', 24: 'r25'},
            37: {16: 'r12', 24: 's39'},
            38: {16: 'r63', 24: 'r63'},
            39: {5: 's19', 16: 'r8'},
            40: {16: 'r98'},
            41: {16: 'r30', 24: 'r30'},
            42: {1: 'r70', 5: 'r70', 7: 'r70', 9: 'r70', 10: 'r70', 16: 'r70', 17: 'r70', 24: 'r70'},
            43: {0: 's74', 1: 'r34', 5: 's71', 6: 's73', 7: 's70', 9: 'r34', 12: 's72', 14: 's63', 22: 'r34'},
            44: {12: 's45'},
            45: {1: 'r43', 8: 'r43', 18: 's47'},
            46: {1: 'r55', 8: 's50'},
            47: {0: 'r24', 1: 'r24', 3: 'r24', 5: 'r24', 6: 'r24', 7: 'r24', 8: 'r24', 9: 'r24', 10: 'r24', 11: 'r24', 12: 'r24', 13: 'r24', 15: 'r24', 22: 'r24'},
            48: {1: 's59'},
            49: {1: 'r83'},
            50: {17: 's51'},
            51: {5: 's53'},
            52: {16: 's58'},
            53: {16: 'r28', 24: 'r28'},
            54: {16: 'r41', 24: 's56'},
            55: {16: 'r84', 24: 'r84'},
            56: {5: 's57'},
            57: {16: 'r97', 24: 'r97'},
            58: {1: 'r72'},
            59: {2: 'r85', 4: 'r85', 5: 'r85'},
            60: {1: 's132'},
            61: {1: 'r7', 9: 'r7'},
            62: {1: 'r2', 9: 'r2', 22: 's98'},
            63: {1: 'r31', 9: 'r31', 22: 'r31'},
            64: {1: 'r45', 9: 'r45', 22: 'r45'},
            65: {0: 's74', 1: 'r61', 3: 'r61', 5: 's71', 6: 's73', 7: 's70', 9: 'r61', 10: 'r61', 12: 's72', 22: 'r61'},
            66: {0: 'r62', 1: 'r62', 3: 'r62', 5: 'r62', 6: 'r62', 7: 'r62', 9: 'r62', 10: 'r62', 12: 'r62', 22: 'r62'},
            67: {0: 'r6', 1: 'r6', 3: 'r6', 5: 'r6', 6: 'r6', 7: 'r6', 8: 's93', 9: 'r6', 10: 'r6', 12: 'r6', 22: 'r6'},
            68: {0: 'r10', 1: 'r10', 3: 'r10', 5: 'r10', 6: 'r10', 7: 'r10', 8: 'r10', 9: 'r10', 10: 'r10', 12: 'r10', 22: 'r10'},
            69: {0: 'r23', 1: 'r23', 3: 'r23', 5: 'r23', 6: 'r23', 7: 'r23', 8: 'r23', 9: 'r23', 10: 'r23', 11: 's85', 12: 'r23', 13: 's86', 15: 's84', 22: 'r23'},
            70: {0: 'r3', 1: 'r3', 3: 'r3', 5: 'r3', 6: 'r3', 7: 'r3', 8: 'r3', 9: 'r3', 10: 'r3', 11: 'r3', 12: 'r3', 13: 'r3', 15: 'r3', 22: 'r3'},
            71: {0: 'r51', 1: 'r51', 3: 'r51', 5: 'r51', 6: 'r51', 7: 'r51', 8: 'r51', 9: 'r51', 10: 'r51', 11: 'r51', 12: 'r51', 13: 'r51', 15: 'r51', 22: 'r51'},
            72: {0: 'r43', 1: 'r43', 3: 'r43', 5: 'r43', 6: 'r43', 7: 'r43', 8: 'r43', 9: 'r43', 10: 'r43', 11: 'r43', 12: 'r43', 13: 'r43', 15: 'r43', 18: 's47', 22: 'r43'},
            73: {0: 's74', 5: 's71', 6: 's73', 7: 's70', 12: 's72'},
            74: {0: 's74', 5: 's71', 6: 's73', 7: 's70', 12: 's72'},
            75: {3: 's81'},
            76: {3: 'r82', 9: 'r82', 10: 'r82'},
            77: {3: 'r13', 9: 's78', 10: 'r13'},
            78: {0: 's74', 5: 's71', 6: 's73', 7: 's70', 12: 's72'},
            79: {3: 'r4', 9: 'r4', 10: 'r4'},
            80: {3: 'r46', 9: 'r46', 10: 'r46'},
            81: {0: 'r23', 1: 'r23', 3: 'r23', 5: 'r23', 6: 'r23', 7: 'r23', 8: 'r23', 9: 'r23', 10: 'r23', 11: 's85', 12: 'r23', 13: 's86', 15: 's84', 22: 'r23'},
            82: {0: 'r66', 1: 'r66', 3: 'r66', 5: 'r66', 6: 'r66', 7: 'r66', 8: 'r66', 9: 'r66', 10: 'r66', 12: 'r66', 22: 'r66'},
            83: {0: 'r52', 1: 'r52', 3: 'r52', 5: 'r52', 6: 'r52', 7: 'r52', 8: 'r52', 9: 'r52', 10: 'r52', 12: 'r52', 22: 'r52'},
            84: {0: 'r64', 1: 'r64', 3: 'r64', 5: 'r64', 6: 'r64', 7: 'r64', 8: 'r64', 9: 'r64', 10: 'r64', 12: 'r64', 22: 'r64'},
            85: {0: 'r77', 1: 'r77', 3: 'r77', 5: 'r77', 6: 'r77', 7: 'r77', 8: 'r77', 9: 'r77', 10: 'r77', 12: 'r77', 22: 'r77'},
            86: {0: 'r87', 1: 'r87', 3: 'r87', 5: 'r87', 6: 'r87', 7: 'r87', 8: 'r87', 9: 'r87', 10: 'r87', 12: 'r87', 22: 'r87'},
            87: {10: 's88'},
            88: {0: 'r11', 1: 'r11', 3: 'r11', 5: 'r11', 6: 'r11', 7: 'r11', 8: 'r11', 9: 'r11', 10: 'r11', 12: 'r11', 22: 'r11'},
            89: {0: 'r78', 1: 'r78', 3: 'r78', 5: 'r78', 6: 'r78', 7: 'r78', 8: 'r78', 9: 'r78', 10: 'r78', 11: 'r78', 12: 'r78', 13: 'r78', 15: 'r78', 22: 'r78'},
            90: {0: 'r95', 1: 'r95', 3: 'r95', 5: 'r95', 6: 'r95', 7: 'r95', 8: 'r95', 9: 'r95', 10: 'r95', 12: 'r95', 22: 'r95'},
            91: {0: 'r15', 1: 'r15', 3: 'r15', 5: 'r15', 6: 'r15', 7: 'r15', 9: 'r15', 10: 'r15', 12: 'r15', 22: 'r15'},
            92: {0: 'r17', 1: 'r17', 3: 'r17', 5: 'r17', 6: 'r17', 7: 'r17', 9: 'r17', 10: 'r17', 12: 'r17', 22: 'r17'},
            93: {5: 's94'},
            94: {0: 'r40', 1: 'r40', 3: 'r40', 5: 'r40', 6: 'r40', 7: 'r40', 9: 'r40', 10: 'r40', 12: 'r40', 22: 'r40'},
            95: {0: 'r79', 1: 'r79', 3: 'r79', 5: 'r79', 6: 'r79', 7: 'r79', 9: 'r79', 10: 'r79', 12: 'r79', 22: 'r79'},
            96: {1: 'r29', 9: 'r29'},
            97: {1: 'r1', 9: 'r1'},
            98: {0: 'r26', 5: 's100', 6: 'r26'},
            99: {0: 's103', 6: 's101'},
            100: {0: 'r67', 6: 'r67'},
            101: {20: 's126'},
            102: {1: 'r60', 9: 'r60', 17: 's9'},
            103: {3: 'r47', 15: 's109', 19: 'r68', 23: 'r68'},
            104: {3: 's123'},
            105: {3: 'r94'},
            106: {3: 'r54'},
            107: {3: 'r89', 24: 'r89'},
            108: {19: 's112', 23: 's110'},
            109: {19: 'r33', 23: 'r33'},
            110: {0: 'r35', 3: 'r35', 6: 'r35', 15: 'r35', 24: 'r35'},
            111: {0: 'r5', 3: 'r14', 6: 'r5', 15: 's116', 24: 'r14'},
            112: {0: 'r93', 3: 'r93', 6: 'r93', 15: 'r93', 24: 'r93'},
            113: {3: 'r37', 24: 'r37'},
            114: {0: 's103', 6: 's101'},
            115: {0: 'r86', 6: 'r86'},
            116: {0: 'r48', 6: 'r48'},
            117: {3: 'r36', 24: 'r36'},
            118: {3: 'r74', 24: 'r74'},
            119: {3: 'r75', 24: 's121'},
            120: {3: 'r57', 24: 'r57'},
            121: {15: 's109', 19: 'r68', 23: 'r68'},
            122: {3: 'r73', 24: 'r73'},
            123: {1: 'r56', 3: 'r56', 9: 'r56', 17: 'r56', 24: 'r56'},
            124: {1: 'r22', 9: 'r22'},
            125: {1: 'r96', 9: 'r96'},
            126: {10: 's127'},
            127: {1: 'r50', 3: 'r50', 9: 'r50', 17: 'r50', 24: 'r50'},
            128: {1: 'r38', 9: 's129'},
            129: {0: 's74', 1: 'r34', 5: 's71', 6: 's73', 7: 's70', 9: 'r34', 12: 's72', 14: 's63', 22: 'r34'},
            130: {1: 'r76', 9: 'r76'},
            131: {1: 'r9', 9: 'r9'},
            132: {2: 'r80', 4: 'r80', 5: 'r80'},
            133: {2: 'r19', 4: 'r19', 5: 'r19'}
        }
        self.__sparse_goto_table: Dict[int, Dict[int, int]] = {
            0: {16: 5, 33: 4, 46: 6, 52: 1, 54: 2, 59: 3},
            2: {16: 5, 33: 4, 46: 6, 59: 133},
            8: {8: 13, 12: 10, 22: 11},
            9: {14: 17, 30: 18},
            10: {8: 13, 22: 16},
            18: {32: 37},
            20: {8: 23, 28: 21, 35: 22},
            27: {8: 23, 28: 28, 35: 22},
            28: {2: 31, 15: 30},
            29: {8: 23, 28: 36, 35: 22},
            30: {2: 32, 34: 34},
            33: {8: 23, 28: 36, 35: 22},
            37: {34: 40, 57: 38},
            39: {30: 41},
            43: {1: 61, 21: 60, 24: 66, 27: 68, 31: 64, 39: 65, 43: 67, 48: 69, 53: 62},
            45: {19: 46},
            46: {38: 48, 55: 49},
            51: {0: 52},
            53: {37: 54},
            54: {17: 55},
            61: {26: 128},
            62: {20: 97, 47: 96},
            65: {24: 95, 27: 68, 43: 67, 48: 69},
            67: {5: 92, 36: 91},
            69: {3: 90, 18: 83},
            72: {19: 89},
            73: {24: 66, 27: 68, 31: 76, 39: 65, 40: 87, 43: 67, 48: 69},
            74: {24: 66, 27: 68, 31: 76, 39: 65, 40: 75, 43: 67, 48: 69},
            76: {13: 77},
            77: {10: 79},
            78: {24: 66, 27: 68, 31: 80, 39: 65, 43: 67, 48: 69},
            81: {3: 82, 18: 83},
            98: {56: 99},
            99: {44: 102},
            102: {8: 125, 42: 124},
            103: {4: 107, 6: 104, 9: 108, 41: 105, 50: 106},
            107: {7: 119},
            108: {29: 111},
            111: {25: 114, 45: 115, 49: 113, 51: 117},
            114: {44: 118},
            119: {58: 120},
            121: {4: 122, 9: 108},
            128: {23: 130},
            129: {1: 131, 24: 66, 27: 68, 31: 64, 39: 65, 43: 67, 48: 69, 53: 62}
        }
        self.__sentence_index_grammar_tuple_mapping: Dict[int, Tuple[str, ...]] = {
            69: ('1', '*2'),
            25: ('1',),
            91: ('*0', '*1'),
            81: ('0',),
            20: ('0',),
            39: ('0', '2'),
            98: ('0', '*1'),
            30: ('1',),
            12: (),
            8: ('0',),
            88: (),
            63: ('*0', '*1'),
            70: ('1',),
            13: ('0', '*1'),
            46: ('1',),
            82: (),
            4: ('*0', '*1'),
            11: ('1',),
            66: ('1', '*3'),
            78: ('0', '*1'),
            3: ('0',),
            95: ('0', '*1'),
            23: (),
            52: ('0',),
            15: ('0', '*1'),
            40: ('1',),
            6: (),
            17: ('*0',),
            36: ('*0', '*1', '*2'),
            74: ('*0', '1'),
            14: (),
            37: ('*0',),
            5: (),
            86: ('*0',),
            68: (),
            33: ('0',),
            75: ('0', '*1'),
            73: ('1',),
            89: (),
            57: ('*0', '*1'),
            50: ('1',),
            56: ('*1',),
            54: ('*0',),
            47: (),
            94: ('*0',),
            61: ('*0',),
            79: ('*0', '1'),
            1: ('0', '*1'),
            22: ('1', '2', '3'),
            2: (),
            29: ('*0',),
            60: (),
            96: ('0',),
            26: (),
            67: ('0',),
            38: ('0', '*1'),
            9: ('1',),
            7: (),
            76: ('*0', '*1'),
            80: ('0', '2'),
            41: ('0', '*1'),
            97: ('1',),
            28: (),
            84: ('*0', '*1'),
            85: ('0', '2', '*3', '4'),
            72: ('*2',),
            55: (),
            83: ('*0',),
            43: (),
            24: ('0',),
            65: ('0', '*1'),
            27: ('*0', '1'),
            19: ('*0', '1'),
            58: ('*0',)
        }
        self.__reduce_symbol_count: List[int] = [1, 2, 0, 1, 2, 0, 0, 0, 1, 2, 1, 3, 0, 2, 0, 2, 1, 1, 1, 2, 1, 1, 4, 0, 1, 2, 0, 2, 0, 1, 2, 1, 1, 1, 0, 1, 3, 1, 2, 3, 2, 2, 1, 0, 1, 1, 2, 0, 1, 1, 3, 1, 1, 1, 1, 0, 3, 2, 1, 1, 0, 1, 1, 2, 1, 3, 4, 1, 0, 5, 3, 1, 4, 2, 2, 2, 2, 1, 2, 2, 4, 1, 0, 1, 2, 6, 1, 1, 0, 0, 1, 2, 1, 1, 1, 2, 1, 2, 3]
        self.__reduce_non_terminal_index: List[int] = [11, 1, 20, 48, 13, 25, 36, 26, 34, 23, 43, 27, 34, 40, 51, 24, 28, 36, 28, 54, 28, 28, 47, 3, 19, 2, 56, 12, 37, 20, 57, 53, 59, 9, 53, 29, 4, 51, 21, 30, 5, 0, 59, 19, 22, 53, 10, 6, 45, 54, 44, 48, 3, 52, 41, 38, 44, 7, 15, 59, 42, 31, 39, 32, 18, 16, 27, 56, 9, 35, 8, 12, 55, 58, 49, 50, 26, 18, 48, 39, 33, 28, 13, 38, 37, 46, 25, 18, 32, 7, 22, 15, 22, 29, 6, 43, 42, 17, 14]

    def parse(self, token_list: List[BosonToken]) -> BosonGrammar:
        grammar: BosonGrammar = BosonGrammar()
        analysis_stack: List[int] = [0]
        symbol_stack: List[BosonGrammarNode] = []
        token_index: int = 0
        while token_index < len(token_list):
            token: BosonToken = token_list[token_index]
            current_state: int = analysis_stack[-1]
            if token.symbol in self.__terminal_index_mapping:
                operation: str = self.__sparse_action_table.get(current_state, {}).get(self.__terminal_index_mapping[token.symbol], 'e')
            else:
                operation: str = 'e'
            operation_flag: str = operation[0]
            if operation_flag == 'e':
                grammar.error_index = token_index
                return grammar
            elif operation_flag == 's':
                analysis_stack.append(int(operation[1:]))
                token_index += 1
                grammar_node: BosonGrammarNode = BosonGrammarNode(token.text)
                symbol_stack.append(grammar_node)
            elif operation_flag == 'r':
                statement_index: int = int(operation[1:])
                reduce_count: int = self.__reduce_symbol_count[statement_index]
                for _ in range(reduce_count):
                    analysis_stack.pop()
                current_state: int = analysis_stack[-1]
                current_non_terminal_index: int = self.__reduce_non_terminal_index[statement_index]
                goto_next_state: int = self.__sparse_goto_table.get(current_state, {}).get(current_non_terminal_index, -1)
                if goto_next_state == -1:
                    raise ValueError(f'Invalid goto action: state={current_state}, non-terminal={current_non_terminal_index}')
                analysis_stack.append(goto_next_state)
                if statement_index in self.__sentence_index_grammar_tuple_mapping:
                    symbol_package: List[BosonGrammarNode] = []
                    for _ in range(reduce_count):
                        symbol_package.insert(0, symbol_stack.pop())
                    grammar_node: BosonGrammarNode = BosonGrammarNode()
                    for node_string in self.__sentence_index_grammar_tuple_mapping[statement_index]:
                        if node_string[0] == '*':
                            for node in symbol_package[int(node_string[1:])]:
                                grammar_node.append(node)
                        else:
                            grammar_node.append(symbol_package[int(node_string)])
                    grammar_node.set_reduce_number(statement_index)
                    symbol_stack.append(grammar_node)
                elif statement_index in {0, 10, 16, 18, 21, 31, 32, 34, 35, 42, 44, 45, 48, 49, 51, 53, 59, 62, 64, 71, 77, 87, 90, 92, 93}:
                    grammar_node: BosonGrammarNode = BosonGrammarNode()
                    for _ in range(reduce_count):
                        grammar_node.insert(0, symbol_stack.pop())
                    grammar_node.set_reduce_number(statement_index)
                    symbol_stack.append(grammar_node)
                else:
                    raise ValueError(f'Invalid reduce number: reduce={statement_index}')
            elif operation_flag == 'a':
                grammar.grammar_tree = symbol_stack[0]
                return grammar
            else:
                raise ValueError(f'Invalid action: action={operation}')
        raise RuntimeError('Analyzer unusual exit.')
